{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import re\n",
    "\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from pylab import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pythonlib import boolean as boolean\n",
    "from pythonlib import boolean_net as boolean_net"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random as random #random could be destroyed by matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def to_bool_charactor(c):\n",
    "    if c=='1':\n",
    "        return True\n",
    "    else:\n",
    "        return False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def to_bool_string(s):\n",
    "    return[to_bool_charactor(x) for x in s]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def file2matrix(path):\n",
    "    fp=open(path,'r')\n",
    "    content=fp.read()\n",
    "    rowlist=content.splitlines()\n",
    "    x=np.array([to_bool_string(x) for x in rowlist])\n",
    "    \n",
    "    return x\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_bool_dict={0:[False,False,False,False],\n",
    "              1:[False,False,False,True],\n",
    "              2:[False,False,True,False],\n",
    "              3:[False,False,True,True],\n",
    "              4:[False,True,False,False],\n",
    "              5:[False,True,False,True],\n",
    "              6:[False,True,True,False],\n",
    "              7:[False,True,True,True],\n",
    "              8:[True,False,False,False],\n",
    "              9:[True,False,False,True]}\n",
    "             \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "bool_list=list(num_bool_dict.values())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "root = \"trainingDigits16x\" #数据文件所在路径\\n\"\n",
    "pathlist = os.listdir(root) # 获取路径下所有数据文件\"\n",
    "\n",
    "random.shuffle(pathlist)\n",
    "test_set=[]\n",
    "for i in range (0,32):\n",
    "    filepath=root+'\\\\'+pathlist[i]\n",
    "    s=pathlist[i]\n",
    "    n=(re.split('_',s))[0]\n",
    "    target=num_bool_dict[int(n)]\n",
    "    input=file2matrix(filepath).reshape(1,256).tolist()[0]\n",
    "    #print(filepath)\n",
    "    test_set.append([input,target])\n",
    "    \n",
    "random.shuffle(pathlist)\n",
    "verify_set=[]\n",
    "for i in range (0,64):\n",
    "    filepath=root+'\\\\'+pathlist[i]\n",
    "    s=pathlist[i]\n",
    "    n=(re.split('_',s))[0]\n",
    "    target=num_bool_dict[int(n)]\n",
    "    input=file2matrix(filepath).reshape(1,256).tolist()[0]\n",
    "    #print(filepath)\n",
    "    verify_set.append([input,target]) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def show_nn(bl1):\n",
    "    fig,axs=plt.subplots(nrows=1, ncols=5, figsize=(12, 6))\n",
    "    axs[0].imshow(np.array([bl1.inode]),vmin=0,vmax=1)\n",
    "    axs[0].set_title('inode')\n",
    "    axs[0].set_axis_off()\n",
    "    axs[1].imshow(bl1.wi,vmin=0,vmax=1)\n",
    "    axs[1].set_title('wi')\n",
    "    axs[1].set_axis_off()\n",
    "    axs[2].imshow(np.array([bl1.hnode]),vmin=0,vmax=1)\n",
    "    axs[2].set_title('hnode')\n",
    "    axs[2].set_axis_off()\n",
    "    axs[3].imshow(bl1.wo,vmin=0,vmax=1)\n",
    "    axs[3].set_title('wo')\n",
    "    axs[3].set_axis_off()\n",
    "    axs[4].imshow(np.array([bl1.onode]),vmin=0,vmax=1)\n",
    "    axs[4].set_title('onode')\n",
    "    axs[4].set_axis_off()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "def show_nparray(nparray):\n",
    "    fig,axs=plt.subplots(nrows=1, ncols=1)\n",
    "    axs.imshow((nparray),vmin=0,vmax=1)\n",
    "    axs.set_title('array')\n",
    "    axs.set_axis_off()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "def to_char_bool(bool):\n",
    "    if bool:\n",
    "        return '1'\n",
    "    else:\n",
    "        return '0'\n",
    "\n",
    "def to_string_boollist(boollist):\n",
    "    temp=[to_char_bool(x) for x in boollist]    \n",
    "    return ''.join(temp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "bl1=boolean_net.booleannet('bl.db',256,8,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "target:  3   result:  8  wrong\n",
      "target:  4   result:  not_in_list  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  7   result:  9  wrong\n",
      "target:  0   result:  9  wrong\n",
      "target:  7   result:  not_in_list  wrong\n",
      "target:  3   result:  5  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  7   result:  9  wrong\n",
      "target:  8   result:  9  wrong\n",
      "target:  3   result:  5  wrong\n",
      "target:  6   result:  1  wrong\n",
      "target:  6   result:  not_in_list  wrong\n",
      "target:  0   result:  8  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  2   result:  5  wrong\n",
      "target:  8   result:  2  wrong\n",
      "target:  6   result:  9  wrong\n",
      "target:  8   result:  5  wrong\n",
      "target:  5   result:  not_in_list  wrong\n",
      "target:  0   result:  9  wrong\n",
      "target:  5   result:  5  right\n",
      "target:  5   result:  not_in_list  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  9   result:  9  right\n",
      "target:  2   result:  1  wrong\n",
      "target:  3   result:  1  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  9   result:  5  wrong\n",
      "target:  0   result:  not_in_list  wrong\n",
      "target:  3   result:  2  wrong\n",
      "target:  9   result:  not_in_list  wrong\n",
      "target:  7   result:  9  wrong\n",
      "target:  1   result:  8  wrong\n",
      "target:  8   result:  9  wrong\n",
      "target:  7   result:  8  wrong\n",
      "target:  1   result:  8  wrong\n",
      "target:  6   result:  3  wrong\n",
      "target:  5   result:  not_in_list  wrong\n",
      "target:  4   result:  5  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  3   result:  5  wrong\n",
      "target:  0   result:  8  wrong\n",
      "target:  8   result:  not_in_list  wrong\n",
      "target:  2   result:  not_in_list  wrong\n",
      "target:  8   result:  9  wrong\n",
      "target:  3   result:  9  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  6   result:  9  wrong\n",
      "target:  3   result:  5  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  8   result:  3  wrong\n",
      "target:  6   result:  9  wrong\n",
      "target:  6   result:  9  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  7   result:  not_in_list  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  9   result:  9  right\n",
      "target:  9   result:  9  right\n",
      "target:  9   result:  5  wrong\n",
      "target:  8   result:  9  wrong\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#train\n",
    "for i in test_set:   \n",
    "    bl1.train(i[0],i[1])\n",
    "    bl1.feedforward()\n",
    "\n",
    "#test\n",
    "right=0\n",
    "right_list=[]\n",
    "for i in verify_set:\n",
    "    bl1.inode=i[0]\n",
    "    bl1.feedforward()\n",
    "    target = bool_list.index(i[1])\n",
    "    try:\n",
    "        result = bool_list.index(bl1.onode)\n",
    "    except:\n",
    "        result ='not_in_list'\n",
    "    #print()    \n",
    "    if bl1.onode==i[1]:\n",
    "        print('target: ',target , '  result: ',result,' right')\n",
    "        right_list.append(target)\n",
    "        right+=1\n",
    "    else:\n",
    "        print('target: ',target , '  result: ',result,' wrong')\n",
    "right\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5, 9, 9, 9]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "right_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "#double hidden node neural network\n",
    "bl1=boolean_net.booleannet('bl.db',256,16,8)\n",
    "bl2=boolean_net.booleannet('bl.db',8,8,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "#train for net with 2 hidenode\n",
    "for i in test_set: \n",
    "    bl1.inode=i[0]\n",
    "    bl1.feedforward()\n",
    "    bl2.inode=bl1.onode\n",
    "    bl2.feedforward()\n",
    "    #backPropagate\n",
    "    bl2.backPropagate(i[1])\n",
    "    bl1.backPropagate(bl2.inode)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "target:  3   result:  9  wrong\n",
      "target:  4   result:  9  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  1   result:  8  wrong\n",
      "target:  7   result:  9  wrong\n",
      "target:  0   result:  9  wrong\n",
      "target:  7   result:  8  wrong\n",
      "target:  3   result:  not_in_list  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  7   result:  9  wrong\n",
      "target:  8   result:  9  wrong\n",
      "target:  3   result:  9  wrong\n",
      "target:  6   result:  9  wrong\n",
      "target:  6   result:  9  wrong\n",
      "target:  0   result:  2  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  2   result:  9  wrong\n",
      "target:  8   result:  not_in_list  wrong\n",
      "target:  6   result:  1  wrong\n",
      "target:  8   result:  9  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  0   result:  not_in_list  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  9   result:  9  right\n",
      "target:  2   result:  9  wrong\n",
      "target:  3   result:  9  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  9   result:  not_in_list  wrong\n",
      "target:  0   result:  9  wrong\n",
      "target:  3   result:  9  wrong\n",
      "target:  9   result:  9  right\n",
      "target:  7   result:  9  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  8   result:  9  wrong\n",
      "target:  7   result:  not_in_list  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  6   result:  6  right\n",
      "target:  5   result:  9  wrong\n",
      "target:  4   result:  9  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  3   result:  9  wrong\n",
      "target:  0   result:  8  wrong\n",
      "target:  8   result:  9  wrong\n",
      "target:  2   result:  9  wrong\n",
      "target:  8   result:  9  wrong\n",
      "target:  3   result:  9  wrong\n",
      "target:  1   result:  8  wrong\n",
      "target:  6   result:  9  wrong\n",
      "target:  3   result:  9  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  8   result:  not_in_list  wrong\n",
      "target:  6   result:  9  wrong\n",
      "target:  6   result:  9  wrong\n",
      "target:  5   result:  9  wrong\n",
      "target:  7   result:  9  wrong\n",
      "target:  1   result:  9  wrong\n",
      "target:  9   result:  8  wrong\n",
      "target:  9   result:  not_in_list  wrong\n",
      "target:  9   result:  not_in_list  wrong\n",
      "target:  8   result:  9  wrong\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#test\n",
    "right=0\n",
    "right=0\n",
    "right_list=[]\n",
    "for i in verify_set:\n",
    "    bl1.inode=i[0]\n",
    "    bl1.feedforward()\n",
    "    bl2.inode=bl1.onode\n",
    "    bl2.feedforward()\n",
    "    target = bool_list.index(i[1])\n",
    "    try:\n",
    "        result = bool_list.index(bl2.onode)\n",
    "    except:\n",
    "        result ='not_in_list'\n",
    "    #print()    \n",
    "    if bl2.onode==i[1]:\n",
    "        print('target: ',target , '  result: ',result,' right')\n",
    "        right_list.append(target)\n",
    "        right+=1\n",
    "    else:\n",
    "        print('target: ',target , '  result: ',result,' wrong')\n",
    "\n",
    "right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[9, 9, 6]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "right_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "x=(np.random.rand(3,3))>0.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "x=np.array([[1,0,1],[0,1,0],[1,0,1]])>0.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "x=np.array([[0,1,0],[1,0,1],[0,1,0]])>0.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAEICAYAAACHyrIWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvDW2N/gAABZlJREFUeJzt3D2IpdUdx/Hff9lOkixERFeMRbAQjCwpTCWpwlrYpBCbRWJvJQiWWgQrTcAylfiCsonYWCwLKQISEIQtRARfIAmOCb6wvoAKsifF3GJjxuwuzuzc/Px8quE8zz1zHrhfzoG5c2etFaDHkcNeALC/RA1lRA1lRA1lRA1lRA1lRA1lRA1lRP09NDNHL2eM/0+iLjIzD8/MOzPz2cy8MTO/3oz/ZmZemZnfzczHSR75lrGfzsyfZ+ajmflwZp6dmWObOR6amT994/c9OTO/v/pPyv8i6i7vJLkzyY+SPJrkmZm5YXPtF0neTXJdkt9+y9gkeSzJ8SS3JrkpySObe59JctdFkR9Ncm+Spw/0ibhioi6y1jq91tpZa11Ya72Q5K0kd2wu76y1nlxrfb3W+mKvsbXW22uts2utr9ZaHyR5IskvN3O/n+QvSe7ZvPauJB+utV67ek/I5RB1kZm5b2bOzcz5mTmf5LYk124u/2OPl/zH2MxcNzPPz8x7M/Npdnfnay+65akkpzY/n4pdeiuJusTM3JzkD0keSPLjtdaxJK9n90idJHv9O943xx7bjN2+1vphdsOdi66/lOT2mbktyd1Jnt2/J2C/iLrHNdkN8oMkmZn7s7tTX4kfJPk8yfmZuTHJQxdfXGt9meSPSZ5L8upa6+/fddHsP1GXWGu9keTxJH9N8q8kP0vyyhVO82iSnyf5JMnLSV7c456nNnM7em+p8SUJXImZ+UmSN5Ncv9b69LDXw3+zU3PZZuZIkgeTPC/o7eVTRFyWmbkmu8f6v2X3z1lsKcdvKOP4DWUO5Pj9qyP32P4v4czOucNewlY7efzEYS9h6529cHr2GrdTQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQxlRQ5lZa+37pBf+ecv+T1rm5PETh72ErXZm59xhL2HrHbn+rdlz/GovBDhYooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyooYyRw9i0pPHTxzEtFXO7Jw77CVsNe+hSzt7Ye9xOzWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUETWUmbXWYa8B2Ed2aigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaigjaijzb0+Yv70yWM3YAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "mask=np.repeat((np.repeat(x,2,axis=0)),2,axis=1)\n",
    "show_nparray(mask)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "bl1=boolean_net.booleannet('bl.db',121,8,4)\n",
    "#convolution  + booleannet\n",
    "#train\n",
    "random.shuffle(test_set)\n",
    "for i in test_set:   \n",
    "    temp=np.array(i[0]).reshape(16,16)\n",
    "    res=boolean.convolution(boolean.otimes_bv_bv,temp,mask)\n",
    "    res=res.reshape(1,121).tolist()[0]\n",
    "    bl1.train(res,i[1])\n",
    "    bl1.feedforward()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "target:  3   result:  8  wrong\n",
      "target:  4   result:  8  wrong\n",
      "target:  1   result:  not_in_list  wrong\n",
      "target:  1   result:  7  wrong\n",
      "target:  7   result:  1  wrong\n",
      "target:  0   result:  0  right\n",
      "target:  7   result:  8  wrong\n",
      "target:  3   result:  not_in_list  wrong\n",
      "target:  5   result:  0  wrong\n",
      "target:  7   result:  7  right\n",
      "target:  8   result:  not_in_list  wrong\n",
      "target:  3   result:  7  wrong\n",
      "target:  6   result:  8  wrong\n",
      "target:  6   result:  8  wrong\n",
      "target:  0   result:  1  wrong\n",
      "target:  5   result:  not_in_list  wrong\n",
      "target:  2   result:  3  wrong\n",
      "target:  8   result:  not_in_list  wrong\n",
      "target:  6   result:  4  wrong\n",
      "target:  8   result:  0  wrong\n",
      "target:  5   result:  0  wrong\n",
      "target:  0   result:  7  wrong\n",
      "target:  5   result:  1  wrong\n",
      "target:  5   result:  0  wrong\n",
      "target:  5   result:  8  wrong\n",
      "target:  9   result:  1  wrong\n",
      "target:  2   result:  0  wrong\n",
      "target:  3   result:  4  wrong\n",
      "target:  5   result:  6  wrong\n",
      "target:  5   result:  not_in_list  wrong\n",
      "target:  9   result:  not_in_list  wrong\n",
      "target:  0   result:  not_in_list  wrong\n",
      "target:  3   result:  8  wrong\n",
      "target:  9   result:  0  wrong\n",
      "target:  7   result:  8  wrong\n",
      "target:  1   result:  4  wrong\n",
      "target:  8   result:  0  wrong\n",
      "target:  7   result:  not_in_list  wrong\n",
      "target:  1   result:  5  wrong\n",
      "target:  6   result:  1  wrong\n",
      "target:  5   result:  2  wrong\n",
      "target:  4   result:  not_in_list  wrong\n",
      "target:  5   result:  8  wrong\n",
      "target:  1   result:  3  wrong\n",
      "target:  3   result:  7  wrong\n",
      "target:  0   result:  5  wrong\n",
      "target:  8   result:  0  wrong\n",
      "target:  2   result:  0  wrong\n",
      "target:  8   result:  not_in_list  wrong\n",
      "target:  3   result:  7  wrong\n",
      "target:  1   result:  1  right\n",
      "target:  6   result:  6  right\n",
      "target:  3   result:  not_in_list  wrong\n",
      "target:  1   result:  7  wrong\n",
      "target:  8   result:  7  wrong\n",
      "target:  6   result:  5  wrong\n",
      "target:  6   result:  6  right\n",
      "target:  5   result:  8  wrong\n",
      "target:  7   result:  8  wrong\n",
      "target:  1   result:  2  wrong\n",
      "target:  9   result:  not_in_list  wrong\n",
      "target:  9   result:  4  wrong\n",
      "target:  9   result:  0  wrong\n",
      "target:  8   result:  6  wrong\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#test\n",
    "right=0\n",
    "right_list=[]\n",
    "for i in verify_set:\n",
    "    temp=np.array(i[0]).reshape(16,16)\n",
    "    res=boolean.convolution(boolean.otimes_bv_bv,temp,mask)\n",
    "    res=res.reshape(1,121).tolist()[0]   \n",
    "    bl1.inode=res\n",
    "    bl1.feedforward()\n",
    "    target = bool_list.index(i[1])\n",
    "    try:\n",
    "        result = bool_list.index(bl1.onode)\n",
    "    except:\n",
    "        result ='not_in_list'\n",
    "    #print()    \n",
    "    if bl1.onode==i[1]:\n",
    "        print('target: ',target , '  result: ',result,' right')\n",
    "        right_list.append(target)\n",
    "        right+=1\n",
    "    else:\n",
    "        print('target: ',target , '  result: ',result,' wrong')\n",
    "right\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 7, 1, 6, 6]"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "right_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "def multi_convolution(oa,mask_set):\n",
    "    rz=len(mask_set)\n",
    "    rx,ry=oa.shape\n",
    "    mx,my=mask_set[0].shape\n",
    "    \n",
    "    rx=rx-mx+1\n",
    "    ry=ry-my+1\n",
    "    temp=np.ones((rz,rx,ry))>0  \n",
    "    n=0\n",
    "\n",
    "    for i in mask_set:\n",
    "        res=boolean.convolution(boolean.otimes_bv_bv,oa,i)\n",
    "        #show_nparray(res)\n",
    "        temp[n]=res\n",
    "        n=n+1\n",
    "    return temp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "mask_set=[]\n",
    "for i in range (0,10):\n",
    "    x=(np.random.rand(3,3))>0.5\n",
    "    mask=np.repeat((np.repeat(x,4,axis=0)),4,axis=1)\n",
    "    mask_set.append(mask)\n",
    "    #show_nparray(mask)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "m1=np.array([[0,0,0],\n",
    "             [1,1,1],\n",
    "             [0,0,0]])\n",
    "m2=np.array([[0,1,0],\n",
    "             [0,1,0],\n",
    "             [0,1,0]])\n",
    "m3=np.array([[1,0,0],\n",
    "             [0,1,0],\n",
    "             [0,0,1]])\n",
    "m4=np.array([[0,0,1],\n",
    "             [0,1,0],\n",
    "             [1,0,0]])\n",
    "m5=np.array([[1,0,1],\n",
    "             [0,1,0],\n",
    "             [1,0,1]])\n",
    "m6=np.array([[1,1,1],\n",
    "             [1,0,0],\n",
    "             [1,0,0]])\n",
    "m7=np.array([[1,1,1],\n",
    "             [0,0,1],\n",
    "             [0,0,1]])\n",
    "m8=np.array([[1,0,0],\n",
    "             [1,0,0],\n",
    "             [1,1,1]])\n",
    "m9=np.array([[0,0,1],\n",
    "             [0,0,1],\n",
    "             [1,1,1]])\n",
    "\n",
    "m10=np.array([[1,1,1],\n",
    "             [0,0,0],\n",
    "             [0,0,0]])\n",
    "\n",
    "m11=np.array([[0,1,1],\n",
    "             [1,0,0],\n",
    "             [0,0,0]])\n",
    "m12=np.array([[1,1,0],\n",
    "             [0,0,1],\n",
    "             [0,0,0]])\n",
    "m21=np.array([[0,0,0],\n",
    "             [1,0,0],\n",
    "             [0,1,1]])\n",
    "m22=np.array([[0,0,0],\n",
    "             [0,0,1],\n",
    "             [1,1,0]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_nparray(m4)\n",
    "#temp=[m1,m2,m3,m4,m5,m6,m7,m8,m9]\n",
    "#temp=[m1,m2,m3,m4,m5]\n",
    "#temp=[m3,m3,m5]\n",
    "temp=[m11,m12,m2,m3,m4,m21,m22]\n",
    "mask_set=[]\n",
    "for i in temp:\n",
    "    mask=np.repeat((np.repeat(i,3,axis=0)),3,axis=1)\n",
    "    mask_set.append(mask)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "root = \"trainingDigits16x\" #数据文件所在路径\\n\"\n",
    "pathlist = os.listdir(root) # 获取路径下所有数据文件\"\n",
    "\n",
    "random.shuffle(pathlist)\n",
    "test_set=[]\n",
    "for i in range (0,32):\n",
    "    filepath=root+'\\\\'+pathlist[i]\n",
    "    s=pathlist[i]\n",
    "    n=(re.split('_',s))[0]\n",
    "    target=num_bool_dict[int(n)]\n",
    "    input=file2matrix(filepath).reshape(1,256).tolist()[0]\n",
    "    #print(filepath)\n",
    "    test_set.append([input,target])\n",
    "    \n",
    "random.shuffle(pathlist)\n",
    "verify_set=[]\n",
    "for i in range (0,64):\n",
    "    filepath=root+'\\\\'+pathlist[i]\n",
    "    s=pathlist[i]\n",
    "    n=(re.split('_',s))[0]\n",
    "    target=num_bool_dict[int(n)]\n",
    "    input=file2matrix(filepath).reshape(1,256).tolist()[0]\n",
    "    #print(filepath)\n",
    "    verify_set.append([input,target])    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_nparray(np.array(test_set[0][0]).reshape(16,16))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9\n",
      "[4, 4, 2, 5, 9, 9, 0, 8, 6]\n",
      "11\n",
      "[0, 2, 0, 5, 0, 1, 6, 4, 0, 1, 4]\n",
      "13\n",
      "[0, 2, 0, 2, 0, 4, 5, 2, 4, 8, 4, 0, 0]\n",
      "12\n",
      "[4, 4, 2, 0, 4, 8, 4, 3, 0, 8, 0, 1]\n",
      "11\n",
      "[2, 3, 3, 8, 3, 1, 9, 3, 1, 1, 4]\n",
      "9\n",
      "[0, 0, 0, 0, 0, 0, 0, 0, 2]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAssAAABpCAYAAADMQ24XAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvDW2N/gAAC0lJREFUeJzt3XmsXGUZx/HvU6khggIWVMqmyCKYaI0aEMFWI6LSYlxAQdmM/qFR44pLguCOCVRFgRiiqICaKsQobSw1hCtogiiCEVOhktZrC8hWKBCFch//eM/Ewzhvi7d3ljt8P8mkc5b3nPdMbu/9zTvveSYyE0mSJEn/a86wOyBJkiSNKsOyJEmSVGFYliRJkioMy5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqQKw7IkSWMoIk6NiF+0ltdExLLW8mRELIiIwyLi+oi4v/n3sOH0WBpNhmVJksbTBHBERMyJiN2BucArASJiX2BH4O/AcuBcYB6wFFgeEfOG02Vp9BiWJUkaQ5l5G7AJWAAsBFYC6yPiBc3yNcDRwK2ZeXFmbs7MHwGrgSVD6rY0crYbdgckSVLfTACLgP2a5xspQfkVzfJ8YF1Xm3XAHoProjTaHFmWJGl8dcLyEc3zCUpYXtg83wDs09Vmb2D94LoojbbIzGH3QZIk9UFEHAD8AbgzM/eLiGcAaymfLO8C7Az8DXg/sAx4K/BtYL/MvHsonZZGjNMwJEkaU5l5S0Q8SJmfTGY+EBG3AXdl5mPAPRGxGPgGcAGwBlhsUJb+y5FlSZIkqcI5y5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSpGmJiDMj4pJh96OfLB0nSVLLkXOOnVaZqJUbbpz2OY+av2DabQdttl3nqqmfxMBPqrHiyLIkSZJUYViWJEkaQxFxUERcHREbI+LmiDimWf+9iDgvIpZHxKaIuC4int9qd1hEXB8R9zf/Htba9ryImGjarQJ27TrnoRHx2+acN0XEokFdb78YliVJksZMRMwFfgFcCTwL+CBwaUQc2OxyPPA5yteerwG+1LR7JrAcOBeYBywFlkfEvKbdDylfob4r8AXg5NY592jafhF4JvBx4LKI2K1vFzoAhmVJkqTxcyiwI3BWZj6SmVcBV1BCMsDlmfm7zNwMXAp0JpQfDdyamRdn5ubM/BGwGlgSEXsDLwdOz8x/Z+avKYG8413AisxckZlTmbkK+D3wxn5fbD8ZliVJksbPfGAyM6da69YBezTP72itf5gSrDvt1nUdq9NuPnBfZj7Uta1jH+DYZgrGxojYCBwO7L5NVzJkhmVJGhERsTYiXtvnczw3IjIirIYkjbcNwF4R0c56ewPrn0C7fbrWddrdDuwSETt0beuYBC7OzJ1bjx0y86zpXcJoMCxLkiSNn+uAh4DTImJuc6PdEuDHW2m3AjggIk6IiO0i4u3AwcAVmbmOMq3icxHx1Ig4vDlmxyWU6RpHRcRTImL7iFgUEXvO9MUNkmFZkiRpzGTmI8AxwBuAu4HzgZMyc/VW2t0DLAY+BtwDnAYszsy7m11OAA4B7gXOAH7QajsJvAn4DHAXZaT5E8zyvOnHcJI0WhZExFLKx6C/pNxpfihlxOZrwCeBx4DPZOZFABGxE/BNyh/Fh4ELgS9n5lREPAX4KnAK8ABwTvtkTdullBtwpoCLgDMy87H+XqakfsvMm4GFPdaf0rV8NbBna/la4KWVY94GHLGFc17X65yzmWFZkkbLccDrgX8Bv6GE3NXAc4CdKDfZHAn8NCJ+lpn3UYLyTsC+lFJPV1LmFn4HeC9llOgllI9kL+s63/eBO4H9gB0od8tPAt/u1wVK0mwyq4fFJWkMnZuZGzLzXkpJpk45p0eBz2fmo5m5AngQOLAZOX478OnM3JSZaymjxyc27Y4Dvp6Zk80xv9I5UUQ8mzIa/eHMfCgz/0kZvX5H/y9TkmYHR5alWSoiHgRe1HwkpvHRXc5pfvP8nqYeanvbjpQvBngqjy/f1C4PNZ8yUtze1rEPMBe4PSI66+Z07S9JT2qOLM+A5iskF83wMU+JiGtn8pgaL5m5o0FZlBt3HuXxpZ7a5aFuB/bq2tYxCfwb2LVV5ukZmfnCfnZYkmYTR5ZngH9YJA1LZj4WEcuAL0XESZSvmP0ocHazyzLgQxFxBWXO8qdabW+PiCuBcyLidMrUjucBe2bmxCCvYxwcNX/B1neqWLnhxoGfczaZ7usjzQTDsjRiIuJU4C2ZuaRZXgPckJnHNcuTlLqWfwT2z8w1Q+usRsUHKTf53Ua5MfBC4LvNtguBA4CbKNUwzgZe02p7EnAW8Bfg6c0xvjqQXkuz3NQd++egz/lkeYM0DKumfhK91huWZ0BErAXeQ/lKx4Mpf6zeDPwdODkzf9/sdxBwAeWGnfWUG3J+3mybRynZtIhy5/vKrnO8gPLH8KWU2oWnZ+ayPl+ahmMC+FrzrUvPpswpfSVAROxLmaf6p+F1T/2Smc/tWj6ztbhnbd+mIsa7KsfcDHykeXSc19p+P/C+5iFJ6uKc5Zl3DOXbcXYGfg58CyAi5lLubL8SeBZlJOjSiDiwaXceJWTvDry7edC03QFYBfywaXs8cH5EOP1jDDXzkDdR3lQtpLxxWt+8YVoIXJOZU0PsoiRJTxqG5Zl3bWauaAr6Xwy8uFl/KGVE8KzMfCQzr6LUMz2+Kf30VuCzTfmmP1Nqn3YsBtZm5kWZuTkzb6DUSn3boC5KAzdB+ZThVc3zqylBeWGzLEmSBsCwPPO6yz5tHxHb0ZRv6hoR7JR32o0yJWZL5Z0OiYiNnQfwTsqXFGg8dcLyEc3zCQzLkiQNnHOWB2cDsFdEzGkF5r2BWyhzkDdTyjutbm3rmAQmMvPIQXVWQzdB+QriOzPzHxHxAOWTiu0oN/ZJkqQBcGR5cK6jlG06LSLmNnWZlwA/bqZsXA6cGRFPi4iDgZNbba8ADoiIE5u2cyPi5c0NgxpDmXkLpYzXNc3yA5QqBb9pfl4kSdIAOLI8IJn5SEQcA5wPfJpSDeOkzOyMJH+AUg3jDsro8kXAq5u2myLidZSRxqWUNzk3UWqpakxl5u5dyy/rWu5Z4kZ1wyjzNF2Wh9q6WpknSZpJhuUZ0Crh9Kuu9WuBaC3fTJlz2usYd1Fu5Kud46/A0dvYVUmSJP0fnIYhSZIkVRiWJUmSpArDsiRJklRhWJYkSZIqvMFPs96Rc45NgJUbbnxcBYHO8pbWA4973tFu197WOU67bS+9zr21Nr2uoXtdr+e92vQ6X/f11vrX/To80f51v069Xrde5+nuhxUOJEmjxLCssbC1QNlr/7buMNcrUPc6Xi2A9upHe7/uc3eva+/fPnb3vr3a9QrBnbZbeg261Y7zRN5YdPej9kbh/+2TNK6GUSpwNv1/25bXZ9XU1veRtiQyZ03ZUUnaJtZZHi/9+hSi82nVuBtGWB7Gz3U/P60axu8Ufzf0T+1nxTnLkiRJUoVhWZIkSaowLEuSJEkVhmVJkiSpwrAsSZIkVVg6TtKTxpzn3Dprajhb7kqSRoMjy5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqSKyMxh90GSpJExdcf+0/rDeNT8BTPdlZG0csON02473ddoW845m0pGajQ5sixJkiRVGJYlSZKkCsOyJEmSVGFYliRJkioMy5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqQKw7IkSZJUYViWJEmSKgzLkiRJUoVhWZIkSaqIzBx2HyRJkqSR5MiyJEmSVGFYliRJkioMy5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqQKw7IkSZJUYViWJEmSKgzLkiRJUoVhWZIkSaowLEuSJEkVhmVJkiSpwrAsSZIkVRiWJUmSpArDsiRJklRhWJYkSZIqDMuSJElShWFZkiRJqjAsS5IkSRWGZUmSJKnCsCxJkiRV/Acd3sPccNP8ZgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "#multi convolution + neurol network\n",
    "for k in range(0,6):\n",
    "    max=0\n",
    "    bl1=boolean_net.booleannet('bl.db',448,8,4)\n",
    "#train\n",
    "\n",
    "    for j in range(0,20):\n",
    "        #bl1=boolean_net.booleannet('bl.db',320,8,4)\n",
    "        random.shuffle(test_set)\n",
    "\n",
    "        for i in test_set:   \n",
    "            temp=np.array(i[0]).reshape(16,16)\n",
    "            res=multi_convolution(temp,mask_set)\n",
    "            res=list(res.flatten())\n",
    "            bl1.train(res,i[1])\n",
    "            bl1.feedforward()\n",
    "\n",
    "        #test\n",
    "        right=0\n",
    "        right_list=[]\n",
    "        for i in verify_set:\n",
    "            temp=np.array(i[0]).reshape(16,16)\n",
    "            res=multi_convolution(temp,mask_set)\n",
    "            res=list(res.flatten())  \n",
    "            bl1.inode=res\n",
    "            bl1.feedforward()\n",
    "            target = bool_list.index(i[1])\n",
    "            try:\n",
    "                result = bool_list.index(bl1.onode)\n",
    "            except:\n",
    "                result ='not_in_list'\n",
    "            #print()    \n",
    "            if bl1.onode==i[1]:\n",
    "                #print('target: ',target , '  result: ',result,' right')\n",
    "                right_list.append(target)\n",
    "                right+=1\n",
    "            else:\n",
    "                pass\n",
    "                #print('target: ',target , '  result: ',result,' wrong')\n",
    "        if right>max:\n",
    "            max=right\n",
    "            max_right_list=right_list\n",
    "            bl_max=bl1\n",
    "    print (max)\n",
    "    print(max_right_list)\n",
    "    show_nn(bl_max)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "13\n",
      "[0, 0, 8, 2, 2, 0, 2, 0, 0, 2, 8, 0, 2]\n",
      "10\n",
      "[4, 6, 4, 9, 4, 9, 6, 9, 9, 6]\n",
      "10\n",
      "[2, 0, 2, 2, 2, 0, 2, 2, 0, 2]\n",
      "15\n",
      "[3, 0, 3, 4, 0, 4, 2, 3, 8, 7, 7, 3, 0, 7, 4]\n",
      "12\n",
      "[3, 4, 2, 2, 2, 5, 2, 1, 7, 3, 3, 2]\n",
      "12\n",
      "[4, 0, 6, 0, 6, 4, 6, 6, 0, 0, 6, 0]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAssAAABpCAYAAADMQ24XAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvDW2N/gAACz9JREFUeJzt3WuMXVUZh/HnLdQQQUAKCuUmiCCYaI0SEMVWI1alxSiCgljU6AeNGK+oJCh4xURRUTCGKCqipgoxQBtLDWEETPAKRkyFSlrGFpBboUAUSl8/rH10c5zVTtuZc+vzS07m7Mvae+1Jm/mfddZ+d2QmkiRJkv7fjH53QJIkSRpUhmVJkiSpwrAsSZIkVRiWJUmSpArDsiRJklRhWJYkSZIqDMuSJElShWFZkiRJqjAsS5IkSRWGZUmSRlBEvCsirmotr4yIxa3l8YiYExHHRMTvIuKh5ucx/emxNJgMy5IkjaYx4NiImBER+wAzgZcDRMTBwC7AncAS4AJgFnA+sCQiZvWny9LgMSxLkjSCMvMOYD0wB5gLLAPWRMTzm+XrgeOB2zPz0szckJk/AVYAC/vUbWng7NjvDkiSpGkzBswDDmner6ME5Zc1y7OB1V1tVgP79q6L0mBzZFmSpNHVCcvHNu/HKGF5bvN+LXBgV5sDgDW966I02CIz+90HSZI0DSLiUOAPwD2ZeUhE7Aqsonyz/Exgd+DvwPuBxcCJwHeAQzLzvr50WhowTsOQJGlEZeZtEfEIZX4ymflwRNwB3JuZTwL3R8QC4BvAt4GVwAKDsvQ/jixLkiRJFc5ZliRJkioMy5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkbZWIOCciftTvfkwnS8dJktRy3IyTLBM1YJatvXmr287Y+/aYwq5oO+TIsiRJklRhWJYkSRpBEXF4RFwXEesi4taIOKFZ//2IuDAilkTE+oi4KSKe22p3TET8LiIean4e09p2UESMNe2WA3t2nfPoiPhNc85bImJer653uhiWJUmSRkxEzASuAq4BngWcAVwWEYc1u5wCnEt57PlK4AtNuz2AJcAFwCzgfGBJRMxq2v2Y8gj1PYHPAae3zrlv0/bzwB7Ax4DLI2KvabvQHjAsS5IkjZ6jgV2A8zLz8cy8FriaEpIBrsjM32bmBuAyYE6z/njg9sy8NDM3ZOZPgBXAwog4ADgSODsz/52Zv6YE8o7TgKWZuTQzN2bmcuD3wBum+2Knk2FZkiRp9MwGxjNzY2vdamDf5v3drfWPUYJ1p93qrmN12s0GHszMR7u2dRwInNRMwVgXEeuAVwD7bNOV9JlhWZIGRESsiojXTPM5nhMRGRFWQ5JG21pg/4hoZ70DgDWTaHdg17pOu7uAZ0bEzl3bOsaBSzNz99Zr58w8b+suYTAYliVJkkbPTcCjwJkRMbO50W4h8NPNtFsKHBoRp0bEjhHxVuAI4OrMXE2ZVnFuRDwtIl7RHLPjR5TpGvMjYoeI2Cki5kXEflN9cb1kWJYkSRoxmfk4cALweuA+4CJgUWau2Ey7+4EFwEeB+4EzgQWZeV+zy6nAUcADwGeAH7bajgNvBM4C7qWMNH+cIc+bkWntdUkaBBGxCvgWsIjyNegvKXeaH00Zsfka8AngSeCszLykabcb8E3KH8XHgIuBL2bmxojYAfgy8E7gYeCrzTlmZuaGpu35lBtwNgKXAJ/JzCd7cMkDyYeSDB4fSqJ+cs6aJA2Wk4HXAf8CbqSE3BXA3sBulJtsjgN+HhG/yMwHKUF5N+BgSqmnayhzC78LvJcySvRiyleyl3ed7wfAPcAhwM6Uu+XHge9M1wVK0jAZ6mFxSRpBF2Tm2sx8gFKSqVPO6Qngs5n5RGYuBR4BDmtGjt8KfCoz12fmKsro8TuadicDX8/M8eaYX+qcKCKeTRmN/lBmPpqZ/6SMXr9t+i9TkoaDI8vSkIqIR4AXZuYd/e6LplR3OafZzfv7m3qo7W27UB4M8DSeWr6pXR5qNmWkuL2t40BgJnBXxH+/qZ7Rtb8kbdccWZ4CzSMk503xMd8ZETdM5TE1WjJzF4OyKDfuPMFTSz21y0PdBezfta1jHPg3sGerzNOumfmC6eywJA0TR5angH9YJPVLZj4ZEYuBL0TEIsojZj8CfKXZZTHwwYi4mjJn+ZOttndFxDXAVyPibMrUjoOA/TJzrJfXMUi25WayXps/e87md5pi/fj9bMt1Lt+4+X2kTTEsSwMmIt4FvDkzFzbLK4E/ZubJzfI4pa7ln4DnZebKvnVWg+IMyk1+d1BuDLwY+F6z7WLgUOAWSjWMrwCvbrVdBJwH/BV4RnOML/ek19KQ60fllGH6MDdsapVTDMtToCn39B7KIx2PoPyxehNwJ3B6Zv6+2e9w4NuUG3bWUG7IubLZNotSsmke5c73ZV3neD7lj+FLKLULz87MxdN8aeqPMeBrzVOXnk2ZU/pygIg4mDJP9c/9656mS2Y+p2v5nNbifrV9m4oYp1WOuQH4cPPquLC1/SHgfc1LktTFOctT7wTK03F2B66k1DMlImZS7my/BngWZSTosog4rGl3ISVk7wO8u3nRtN0ZWA78uGl7CnBRRDj9YwQ185DXUz5UzaV8cFrTfGCaC1yfmX6xKElSDxiWp94Nmbm0Keh/KfCiZv3RlBHB8zLz8cy8llLP9JSm9NOJwKeb8k1/odQ+7VgArMrMSzJzQ2b+kVIr9S29uij13BjlW4ZXNu+vowTluc2yJEnqAcPy1Osu+7RTROxIU76pa0SwU95pL8qUmE2VdzoqItZ1XsDbKQ8p0GjqhOVjm/djGJYlSeo55yz3zlpg/4iY0QrMBwC3UeYgb6CUd1rR2tYxDoxl5nG96qz6bozyCOJ7MvMfEfEw5ZuKHSk39kmSpB5wZLl3bqKUbTozImY2dZkXAj9tpmxcAZwTEU+PiCOA01ttrwYOjYh3NG1nRsSRzQ2DGkGZeRuljNf1zfLDlCoFNzb/XiRJUg84stwjmfl4RJwAXAR8ilINY1FmdkaSP0CphnE3ZXT5EuBVTdv1EfFaykjj+ZQPObdQaqlqRGXmPl3LL+1anrDEjeo23v28rSrztC01Xre2zJP1czdv+caf+X9A0rQzLE+BVgmnX3WtXwVEa/lWypzTiY5xL+VGvto5/gYcv41dlSRJ0hZwGoYkSZJUYViWJEmSKgzLkiRJUoVhWZIkSarwBj8NveNmnPR/FQ667+pv33G/bO3NzJ89Z9L7dNa392+v697ebjdRdYGJztPdfqJ+dh93S/tXW95U/ybaZ7LnnczvaqJzW+FAkjRIDMsaet1hsvO+vW1T4bV9nE679s/O+olC50TBtvs4tXO3+9bRPkftfXcfutt3X/Om+lv7ndU+THRf30Tnra2b6HomCv9Svw1T2b5t+T/Tj+uUhpFhWUNvxt63B8Dy1oPE2+8nWjfR9i1d371uU8efzLkne/7JnKf75+b6NJk+bsl5a+smMtn9JEnqB+csS5IkSRWGZUmSJKnCsCxJkiRVGJYlSZKkCsOyJEmSVGE1DEnbjU7llC3Vj0od20t1kO3lOiUNL0eWJUmSpArDsiRJklRhWJYkSZIqDMuSJElShWFZkiRJqjAsS5IkSRWWjpMkaUjNnz1nqM65bO3NU9iT/lu+8WdbVY5Sw8WRZUmSJKnCsCxJkiRVGJYlSZKkCsOyJEmSVGFYliRJkioMy5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqQKw7IkSZJUYViWJEmSKgzLkiRJUkVkZr/7IEmSJA0kR5YlSZKkCsOyJEmSVGFYliRJkioMy5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqQKw7IkSZJUYViWJEmSKgzLkiRJUoVhWZIkSaowLEuSJEkVhmVJkiSpwrAsSZIkVRiWJUmSpArDsiRJklRhWJYkSZIqDMuSJElShWFZkiRJqjAsS5IkSRWGZUmSJKniP74r1RGO+mxdAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAssAAABpCAYAAADMQ24XAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvDW2N/gAAC2ZJREFUeJzt3XuMXGUZx/Hvs1JDBAUpKiw3RS6KidaoEVFsNdaqtBgvoHgBNPqHRo1XFBMU75hoVRSMIYqKqClijNLGUmNYQRO8ghFTaSWtawsISKFAFMo+/vGeicdx3m7Z7s7MTr+fZLJzLu8579lQ5rfvvOc5kZlIkiRJ+n9jg+6AJEmSNKwMy5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqQKw7IkSZJUYViWJEmSKgzLkiSNoIh4U0T8pLW8MSJWtZYnI2JRRJwQEb+JiLuanycMpsfScDIsS5I0miaAEyNiLCIOBhYAzwWIiCOBfYG/AauB84GFwEpgdUQsHEyXpeFjWJYkaQRl5k3AdmARsBhYC2yJiCc1y1cDJwEbMvOSzNyRmd8D1gMrBtRtaejsNegOSJKkOTMBLAGOat5vowTl5zTL48DmrjabgUP610VpuDmyLEnS6OqE5ROb9xOUsLy4eb8VOKKrzeHAlv51URpukZmD7oMkSZoDEXEM8Dvg1sw8KiIeBWyifLP8aGB/4K/A24FVwKuArwFHZebtA+m0NGSchiFJ0ojKzBsj4h7K/GQy8+6IuAm4LTMfBO6IiOXAl4CvAhuB5QZl6b8cWZYkSZIqnLMsSZIkVRiWJUmSpArDsiRJklRhWJYkSZIqDMuSJEmakYg4NyK+M+h+zCVLx0mS1LJ07JQ9okzU2q3XzajdsvFFfT/n7hg7aEP0/aQaKY4sS5IkSRWGZUmSpBEUEU+OiKsiYltE3BARJzfrvxkRF0TE6ojYHhHXRsQTW+1OiIjfRMRdzc8TWtueEBETTbt1wIFd5zw+In7VnPP6iFjSr+udK4ZlSZKkERMRC4CfAFcCjwXeCVwaEcc2u5wGfIzy2PONwKeadgcAq4HzgYXASmB1RCxs2n2X8gj1A4FPAGe0znlI0/aTwAHA+4HLI+Ixc3ahfWBYliRJGj3HA/sC52Xm/Zn5c+AKSkgG+GFm/jozdwCXAp3J6CcBGzLzkszckZnfA9YDKyLicOBZwDmZ+e/M/AUlkHe8AViTmWsycyoz1wG/BV421xc7lwzLkiRJo2ccmMzMqda6zcAhzftbWuvvowTrTrvNXcfqtBsH7szMe7u2dRwBnNJMwdgWEduA5wEH79aVDJhhWZKGRERsiogXzfE5Hh8RGRFWQ5JG21bgsIhoZ73DgS270O6IrnWddjcDj46Ifbq2dUwCl2Tm/q3XPpl53swuYTgYliVJkkbPtcC9wFkRsaC50W4F8P1p2q0BjomI10XEXhHxGuA44IrM3EyZVvGxiHh4RDyvOWbHdyjTNZZFxMMiYu+IWBIRh872xfWTYVmSJGnEZOb9wMnAS4HbgQuB0zNz/TTt7gCWA+8D7gDOApZn5u3NLq8Dng38E/go8O1W20ng5cCHgdsoI80fYJ7nTb+Gk6ThsigiVlK+Bv0p5U7z4ykjNl8APgg8CHw4My8GiIj9gC9TPhTvAy4CPp2ZUxHxMOCzwJnA3cDn2ydr2q6k3IAzBVwMfDQzH5zby5Q01zLzBmBxj/Vndi1fBRzaWr4GeEblmDcBJ+7knNf2Oud8ZliWpOFyKvAS4F/ALykhdz1wELAf5SabpcAPIuJHmXknJSjvBxxJKfV0JWVu4deBt1JGiZ5O+Ur28q7zfQu4FTgK2Idyt/wk8LW5ukBJmk/m9bC4JI2g8zNza2b+k1KSqVPO6QHg45n5QGauAe4Bjm1Gjl8DnJ2Z2zNzE2X0+I1Nu1OBL2bmZHPMz3ROFBGPo4xGvzsz783Mf1BGr18795cpSfODI8vSPBUR9wBPbb4S0+joLuc03ry/o6mH2t62L+XBAA/nf8s3tctDjVNGitvbOo4AFgA3R0Rn3VjX/pK0R3NkeRY0j5BcMsvHPDMirpnNY2q0ZOa+BmVRbtx5gP8t9dQuD3UzcFjXto5J4N/Aga0yT4/KzKfMZYclaT5xZHkW+MEiaVAy88GIWAV8KiJOpzxi9r3A55pdVgHviogrKHOWP9Rqe3NEXAl8PiLOoUzteAJwaGZO9PM6hsnardfNqN2y8UXT7zTLZtpXmHl/d+ecM7U7v9t1U9PvI+2MYVkaMhHxJuCVmbmiWd4I/D4zT22WJyl1Lf8AHJ2ZGwfWWQ2Ld1Ju8ruJcmPgRcA3mm0XAccA11OqYXwOeGGr7enAecCfgUc2x/hsX3otzXNLx07Jfp9zvv2xMlODuM6xgzZEr/WG5VkQEZuAt1Ae6Xgc5cPqFcDfgDMy87fNfk8Gvkq5YWcL5YacHzfbFlJKNi2h3Pm+tuscT6J8GD6DUrvwnMxcNceXpsGYAL7QPHXpcZQ5pc8FiIgjKfNU/zi47mmuZObju5bPbS0eWtu3qYjxhsoxdwDvaV4dF7S23wW8rXlJkro4Z3n2nUx5Os7+wI+BrwBExALKne1XAo+ljARdGhHHNu0uoITsg4E3Ny+atvsA64DvNm1PAy6MCKd/jKBmHvJ2yh9Viyl/OG1p/mBaDFydmX6xKElSHxiWZ981mbmmKeh/CfC0Zv3xlBHB8zLz/sz8OaWe6WlN6adXAR9pyjf9iVL7tGM5sCkzL87MHZn5e0qt1Ff366LUdxOUbxme37y/ihKUFzfLkiSpDwzLs6+77NPeEbEXTfmmrhHBTnmnx1CmxOysvNOzI2Jb5wW8nvKQAo2mTlg+sXk/gWFZkqS+c85y/2wFDouIsVZgPhy4kTIHeQelvNP61raOSWAiM5f2q7MauAnKI4hvzcy/R8TdlG8q9qLc2CdJkvrAkeX+uZZStumsiFjQ1GVeAXy/mbLxQ+DciHhERBwHnNFqewVwTES8sWm7ICKe1dwwqBGUmTdSynhd3SzfTalS8MvmvxdJktQHjiz3SWbeHxEnAxcCZ1OqYZyemZ2R5HdQqmHcQhldvhh4QdN2e0S8mDLSuJLyR871lFqqGlGZeXDX8jO7lnuWuFHd1C1H973M0yBq2e459XMv89+ApDlnWJ4FrRJOP+tavwmI1vINlDmnvY5xG+VGvto5/gKctJtdlSRJ0kPgNAxJkiSpwrAsSZIkVRiWJUmSpArDsiRJklThDX6a95aOndKzwkH7zv5l44t6Lrd/1o7Ra1vnWO1t7X27t/c6Tq0/u9p+uv125fqnW26v79X/6SoZdB+jl+5zWOFAkjRMDMua93oFxl777Cy01cJsrxC5s3bt5emCbq9AOt21dAf87ra9trXPvavBtfY77LWuO+z2+h3Ufhfd5xpE6TKp255Sem8+9df/N2iQDMua98YO2hAA66Z2vl97e+d9r3W1Ng91n+mO/VCO2eu4O7ue2rl7bd+V9TuzK8d/qMeUJGlYOGdZkiRJqjAsS5IkSRWGZUmSJKnCsCxJkiRVGJYlSZKkCqthSNpjdCqn9NMgqn/Mp4oj86mvkvZMjixLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqQKw7IkSZJUYViWJEmSKiIzB90HSZKGxtQtR8/og3HZ+KIZn3Pt1utm3Hamdqe/MzXT69ydvq6buqzvJSM1WhxZliRJkioMy5IkSVKFYVmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqQKw7IkSZJUYViWJEmSKgzLkiRJUoVhWZIkSaowLEuSJEkVhmVJkiSpwrAsSZIkVURmDroPkiRJ0lByZFmSJEmqMCxLkiRJFYZlSZIkqcKwLEmSJFUYliVJkqQKw7IkSZJUYViWJEmSKgzLkiRJUoVhWZIkSaowLEuSJEkVhmVJkiSpwrAsSZIkVRiWJUmSpArDsiRJklRhWJYkSZIqDMuSJElShWFZkiRJqjAsS5IkSRWGZUmSJKnCsCxJkiRVGJYlSZKkCsOyJEmSVGFYliRJkir+Axgy6B0Fqi5QAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "#multi convolution + neurol network\n",
    "for k in range(0,6):\n",
    "    max=0\n",
    "    bl1=boolean_net.booleannet('bl.db',448,8,4)\n",
    "    bl1_mirr=boolean_net.booleannet('bl.db',4,8,448)\n",
    "#train\n",
    "\n",
    "    for j in range(0,20):\n",
    "        #bl1=boolean_net.booleannet('bl.db',320,8,4)\n",
    "        random.shuffle(test_set)\n",
    "\n",
    "        for i in test_set:   \n",
    "            temp=np.array(i[0]).reshape(16,16)\n",
    "            res=multi_convolution(temp,mask_set)\n",
    "            res=list(res.flatten())\n",
    "            bl1.train(res,i[1])\n",
    "            bl1.feedforward()\n",
    "                    #copy from origin nn weight\n",
    "            bl1_mirr.wi=bl1.wo.T\n",
    "            bl1_mirr.wo=bl1.wi.T\n",
    "\n",
    "            bl1_mirr.train(i[1],i[0])\n",
    "\n",
    "            bl1_mirr.feedforward()\n",
    "             #copy back origin nn weight\n",
    "            #bl1.wi=bl1_mirr.wo.T\n",
    "            bl1.wo=bl1_mirr.wi.T \n",
    "\n",
    "        #test\n",
    "        right=0\n",
    "        right_list=[]\n",
    "        for i in verify_set:\n",
    "            temp=np.array(i[0]).reshape(16,16)\n",
    "            res=multi_convolution(temp,mask_set)\n",
    "            res=list(res.flatten())  \n",
    "            bl1.inode=res\n",
    "            bl1.feedforward()\n",
    "            target = bool_list.index(i[1])\n",
    "            try:\n",
    "                result = bool_list.index(bl1.onode)\n",
    "            except:\n",
    "                result ='not_in_list'\n",
    "            #print()    \n",
    "            if bl1.onode==i[1]:\n",
    "                #print('target: ',target , '  result: ',result,' right')\n",
    "                right_list.append(target)\n",
    "                right+=1\n",
    "            else:\n",
    "                pass\n",
    "                #print('target: ',target , '  result: ',result,' wrong')\n",
    "        if right>max:\n",
    "            max=right\n",
    "            max_right_list=right_list\n",
    "            bl_max=bl1\n",
    "    print (max)\n",
    "    print(max_right_list)\n",
    "    show_nn(bl_max)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
